<template>
  <h1>JS调用摄像头录制音频视频并提供下载</h1>
  <video ref="video" autoplay playsinline style="border: 1px solid black;width: 320px;height: 240px;"></video>
  <button ref="startButton" style="margin-top: 10px;" v-on:click="startRecording">开始录制</button>
  <button ref="stopButton" style="margin-top: 10px;" v-on:click="stopRecording" :disabled="disabledStopBtn">停止录制</button>
  <a ref="downloadLink" style="display: none;">下载视频</a>
</template>

<script lang="js" setup>
import {ref} from "vue";

// video 标签 ref
const video = ref(null);
// 开始录制 按钮 ref
const startButton = ref(null);
// 停止录制 按钮 ref
const stopButton = ref(null);
// 停止录制 按钮 是否禁用
const disabledStopBtn = ref(true);
// 下载视频 a标签 ref
const downloadLink = ref(null);
// 媒体流
let stream = null;
// 录制视频和音频
let mediaRecorder = null;
// 存储录制的视频片段
let recordedChunks = [];

/**
 * 开始录制
 * @returns {Promise<void>}
 */
async function startRecording() {
  try {
    // 请求获取摄像头和麦克风权限，并尝试获取媒体流
    stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    // 将媒体流显示到 video 元素上
    video.value.srcObject = stream;
    // 创建录制对象
    mediaRecorder = new MediaRecorder(stream);
    // 监听 MediaRecorder 的 dataavailable 事件，将录制的视频片段添加到 recordedChunks 数组中
    mediaRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        recordedChunks.push(event.data);
      }
    };
    // 监听 MediaRecorder 的 stop 事件，生成 Blob 对象并创建下载链接
    mediaRecorder.onstop = () => {
      const blob = new Blob(recordedChunks, { type: 'video/webm' });
      downloadLink.value.href = URL.createObjectURL(blob);
      downloadLink.value.download = 'recorded_video.webm';
      downloadLink.value.style.display = 'block';
    };
    // 开始录制
    mediaRecorder.start();
    // 开始录制后，允许点击停止录制按钮
    disabledStopBtn.value = false;
  } catch (err) {
    console.error('访问媒体设备时出现错误: ', err);
  }
}

/**
 * 停止录制
 * @returns {Promise<void>}
 */
async function stopRecording() {
  if (stream) {
    stream.getTracks().forEach(track => track.stop());
  }
  if (mediaRecorder) {
    mediaRecorder.stop();
  }
  // 停止录制后，禁用掉停止录制按钮
  disabledStopBtn.value = true;
}

</script>